مشخصات مقاله
-
2170
-
0.0
-
13766
-
0
-
1
سرویس (احراز هویت) Authentication در Laravel
سرویس (احراز هویت) Authentication
فهرست محتوا
-
مقدمه
- ملاحظاتی درباره ی پایگاه داده
-
سنجش هویت کاربر - authentication
- Routing (آدرس دهی)
- View ها
- سنجش هویت کاربر (Authenticating)
- بازیابی اطلاعات کاربر احراز هویت شده
- افزایش امنیت route ها و حافظت از آن ها
- جلوگیری از ورود یا لاگین (authentication throttling)
-
احراز هویت کاربران به صورت دستی
- به خاطر سپردن اطلاعات کاربران
- دیگر روش های اعتبار سنجی
-
احراز هویت ساده ی HTTP
- احراز هویت ساده HTTP ناپایدار (HTTP Basic Authentication)
-
تنظیم و بازگردانی مجدد گذرواژه (Reset کردن پسورد)
- ملاحظات پایگاه داده
- آدرس دهی Routing
- View ها
- پس از بازگردانی گذرواژه (کنترلر بازگردانی و تنظیم مجدد گذرواژه)
- سفارشی سازی (customization)
- احراز هویت از طریق شبکه ی اجتماعی
- افزودن Guard های اختصاصی
- افزودن User Provider های اختصاصی
- رخدادها (Event)
مقدمه
لاراول با امکانات و ابزار قدرتمندی که در اختیار برنامه نویس قرار می دهد پروسه ی پیاده سازی احراز هویت (authentication) را بسیار آسان کرده است. در حقیقت تقریبا همه چیز به صورت آماده و پیکربندی شده می باشد. فایل پیکربندی (config) در آدرس config/auth.php مقیم می باشد. فایل مزبور دربردارنده ی گزینه های متعددی به همراه مستندات و توضیحات برای هر یک می باشد که به وسیله ی آن ها می توانید رفتار و عملکرد سرویس های authentication را ویرایش و تنظیم نمایید.
در اصل امکانات و ابزار authentication لاراول از guards ها و provider ها تشکیل می شود. Guard ها تعریف می کنند چگونه کاربر برای هر درخواست احراز هویت می شود. لاراول به همراه یک guard به نام session عرضه می شود که وضعیت (state) را به وسیله ی محل ذخیره سازی و حافظه ی مخصوص session (session storage) و کوکی ها نگه داشته و ضبط می کند. همچنین این فریم ورک guard دیگری به نام token را ارائه می دهد که با ارسال API token به همراه هر درخواست کاربر را احراز هویت می کند.
Provider ها تعیین می کنند چگونه کاربران از حافظه ی ماندگار (persistent storage) بازیابی شوند. چارچوب نرم افزاری laravel همچنین با عرضه ی ابزار ORM ای که تحت عنوان Eloquent شناخته می شود و نیز query builder (ابزار کوئری ساز پایگاه داده)، از قابلیت بازیابی اطلاعات کاربران پشتیبانی می نماید. با این وجود شما می توانید در صورت نیاز provider هایی اضافی بر آنچه لاراول فراهم می کند برای رفع نیازهای اپلیکیشن خود تعریف نمایید.
اگر همه چیز کمی گیج کننده به نظر می رسد باید بگیم که جایی هیچ نگران نیست. بیشتر برنامه های تحت وب نیازی به ویرایش پیکربندی پیش فرضauthentication پیدا نمی کنند.
ملاحظات پایگاه داده
به صورت پیش فرض، لاراول از مدل App\User مقیم در پوشه ی app استفاده می کند. می توانید از این مدل به همراه درایور authenticationپیش فرض Eloquent استفاده نمایید. اگر اپلیکیشن شما از ابزار Eloquent استفاده نمی کند، در آن صورت می توانید از درایورauthentication به نام database که مبتنی بر query builder لاراول می باشد، برای سنجش هویت کاربران سایت بهره بگیرید.
در زمان تنظیم و ساخت schema ی پایگاه داده برای مدل App\User، به خاطر داشته باشید که ستون password دارای طولی با حداقل 60 کاراکتر باشد که البته حالت پیش فرض با تعداد حداکثر کاراکتر 255 نیز گزینه ی مناسبی به نظر می رسد.
همچنین بایستی اطمینان حاصل کنید که جدول users شما دارای حداقل یک ستون nullable (null پذیر) رشته ای به نام remember token باطول حداقل 100 کاراکتر باشد. در این ستون یک token برای session های "remember me" ذخیره می شود (مقدار remember me در این ستون نگهداری می شود). این کار را می توان با استفاده از دستور $table->rememberToken(); در یک migration انجام داد.
سنجش هویت کاربر - authentication
لاراول به همراه دو کنترلر authentication کاملا آماده و تنظیم شده ارائه می شود که تحت فضای نام (namespace)App\Http\Controllers\Auth قابل دسترسی می باشند. کنترلر AuthController ثبت نام و سنجش هویت کاربران جدید (user registration&authentication) را مدیریت می کند، درحالی که PasswordController حاوی منطق لازم برای کمک به کاربران جهت بازگردانی و تنظیم مجدد گذرواژه ی فراموش شده ی آن ها می باشد. دو کنترلر نام برده هریک از trait (مشخصه) خاصی برای دسترسی به متدهای مورد نیاز خود استفاده می کنند. در بیشتر برنامه هایی که می نویسید نیازی به ویرایش این کنترلرها نیست.
Routing (آدرس دهی)
لاراول با ارائه ی دستور ساده ی php artisan make:auth به شما این مکان را می دهد تا بدون نیاز به کدنویسی تمامی route ها و view ها مورد نیاز برای سنجش هویت کاربر را ایجاد (scaffold) نمایید.
این دستور را می بایست برای اپلیکیشن هایی جدید که قصد ساخت آن ها را دارید فراخوانی کنید. به دنبال اجرای دستور ذکر شده view های ثبت ورود (لاگین) و ثبت نام کاربر عضو جدید و نیز route های مورد نیاز برای end-point های سنجش هویت کاربر همگی بدون نیاز به کدنویسی نصب می شوند.
دستور آرتیزان php artisan make:auth همچنین یک HomeController ایجاد می کند که post-login request ها (درخواست های پس از ثبت ورود کاربر) را به dashboard اپلیکیشن تحویل و سرویس دهی می کند. با این حال شما آزادید این کنترلر را بسته با نیاز اپلیکیشن خود سفارشی تنظیم نمایید.
View ها
همان طور که در بخش قبلی گفته شد، دستور php artisan make:auth تمامی view های مورد نیاز برای سنجش هویت را ایجاد کرده و آن ها را در پوشه ی resources/views/auth قرار می دهد.
دستور make:auth همچنین پوشه ی resources/views/layouts را ایجاد می کند که دربردارنده ی یک layout پایه (طرح کلی) برای اپلیکیشن تحت وب شما می باشد. تمامی این view ها از فریم ورکBootstrap CSS استفاده می کنند. البته لاراول به شما این اختیار را می دهد تا view ها را در صورت نیاز ویرایش و به صورت سفارشی تنظیم نمایید.
سنجش هویت کاربر (Authenticating)
حال که route ها و view ها را نصب کرده و برای کنترلرهای authentication آماده در دست دارید، دیگر می توانید ثبت نام و سنجش هویت کاربر جدید در سایت خود را مدیریت نمایید. برای اجرای برنامه و دسترسی به آن کافی است از یک مرورگر متعارف همچون IE استفاده کنید. خواهید دید که برنامه ی شما به موجب داشتن کنترلرهای Authentication (که از پیش حاوی منطق لازم ارائه شده توسط trait ها می باشد) قادر است کاربران جاری را احراز هویت نموده و اطلاعات کاربران عضو جدید را در پایگاه داده ذخیره کند.
تنظیم و سفارشی سازی مسیر (Path Customization)
پس از اینکه کاربر با موفقیت احراز هویت شد، برنامه کاربر را به آدرس (URI) " / " هدایت (redirect) می کند. شما می توانید با تعریف خاصیت (property) redirectTo در کنترلر AuthController، صفحه ای که کاربر پس از سنجش هویت به آن ارجاع داده (redirect) می شود را به صورت اختصاصی تنظیم نمایید:
protected $redirectTo = '/home';
حال چنانچه کاربر با موفقیت احراز هویت نشد، برنامه وی را به صورت خودکار به صفحه ی ثبت ورود (login form location) بازگشت (redirect back) می دهد.
سفارشی سازی و تنظیم guard
لاراول این اجازه را به شما می دهد تا guard مورد استفاده برای احراز هویت کاربران را سفارشی تنظیم نمایید. برای شروع، لازم است خاصیت (property) guard را در کنترلر AuthController تعریف نمایید. مقدار این property بایستی با مقدار خاصیت guard، تنظیم شده در فایل پیکربندی auth.php، مطابقت و همخوانی داشته باشد:
protected $guard = 'admin';
تنظیم سفارشی اعتبارسنجی (validation) و ذخیره سازی (storage)
برای تنظیم و ویرایش فیدهای الزامی (که باید پیش از ارسال فرم به سرور، کاربر برای ثبت نام در برنامه مقدار در آن ها وارد کند) یا سفارشی سازی نحوه ی درج و وارد شدن سطرهای مربوط به کاربر جدید در پایگاه داده، می بایست کلاس AuthController را اصلاح نمایید. کلاس مزبور وظیفه ی اعتبارسنجی و ایجاد حساب های کاربری جدید در اپلیکیشن را بر عهده دارد.
متد validator از کلاس AuthController دربردارنده ی معیارها و قواعد اعتبارسنجی (validation rules) برای سنجش اعتبار کاربران جدید در برنامه ی شما می باشد. شما می توانید این متد را مطابق نیاز خود تغییر دهید.
تابع Createاز کلاس ذکر شده نیز مسئول ایجاد رکوردهای جدید App\User در پایگاه داده می باشد (درج اطلاعات مربوط به کاربر جدید در بانک اطلاعاتی می باشد).
بازیابی اطلاعات کاربر احراز هویت شده
برای بازیابی و دسترسی به کاربر احراز هویت شده چند روش وجود دارد. در روش اول می توانید با استفاده از فاساد Auth به کاربر سنجش هویت شده دسترسی داشته باشید:
$user = Auth::user();
یا می توانید، پس از اینکه کاربر احراز هویت و authenticate شد، از طریق نمونه ی Illuminate\Http\Request به اطلاعات کاربر سنجش هویت شده دسترسی داشته باشید. به خاطر داشته باشید که کلاس های اعلان نوع (type-hint) شده خود به صورت خودکار به داخل متدهای کنترلر تزریق می شوند:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class ProfileController extends Controller
{
public function updateProfile(Request $request)
{
if ($request->user()) {
// $request->user() returns an instance of the authenticated user...
}
}
}
بررسی اینکه آیا کاربر جاری احراز هویت شده یا خیر
برای بررسی اینکه آیا کاربر به برنامه ی شما وارد شده (login کرده) یا خیر، می توانید متد check را داخل Auth façade صدا بزنید. این متد در صورتی که کاربر از پیش احراز هویت شده باشد، مقدار true را برمی گرداند:
if (Auth::check()) {
// The user is logged in...
}
البته می توان پیش از اینکه به کاربر اجازه ی دسترسی به route / controller های خاصی را بدهید، بررسی کرد آیا آن کاربر احراز هویت شده یا خیر. این کار از طریق middleware ای به نام auth صورت می پذیرد.
افزایش امنیت route ها و حافظت از آن ها
Route middleware به شما این امکان را می دهد تا دسترسی به route معین را تنها به کاربران تصدیق هویت شده محدود نمایید. لاراول برای این منظور یک middleware به نام auth در نظر گرفته که در آدرس app\Http\Middleware\Authenticate.php نگهداری می شود. کافی است این middleware را به تعریف route مورد نظر الحاق کنید:
// Using A Route Closure...
Route::get('profile', ['middleware' => 'auth', function() {
// Only authenticated users may enter...
}]);
// Using A Controller...
Route::get('profile', [
'middleware' => 'auth',
'uses' => 'ProfileController@show'
]);
اگر از کلاس های کنترلر استفاده می کنید، دیگر لازم نیست که middleware نام برده را مستقیما در تعریف route اضافه نمایید. بلکه کافی است این middleware را از تابع constructor کلاس کنترلر فراخوانی نمایید:
public function __construct()
{
$this->middleware('auth');
}
تعیین کردن guard برای اجرای سنجش هویت
به هنگام الحاق کردن auth به route، همچنین می توانید تعیین کنید کدام guard برای اجرای احراز هویت مورد استفاده قرار گیرد:
Route::get('profile', [
'middleware' => 'auth:api',
'uses' => 'ProfileController@show'
]);
Guard مشخص شده باید با یکی از کلیدهای موجود آرایه ی guards فایل کانفیگ auth.php همخوانی داشته باشد.
جلوگیری از ورود یا لاگین (authentication throttling)
اگر از کلاس درون ساخته ی لاراول به نام AuthController استفاده می کنید، در آن صورت می توان با استفاده از مشخصه ی (trait)Illuminate\Foundation\Auth\ThrottlesLoginsتلاش ها برای ورود به برنامه ی تحت وب را بند آورده (throttle) یا متوقف کرد. در حالت پیش فرض، اگر کاربر نتواند گذرواژه و نام کاربری صحیح (credentials) را پس از بارها تلاش برای لاگین ارائه نماید، در آن صورت به مدت 1 دقیقه قادر نخواهد بود به برنامه ی شما وارد شود و تلاش او برای لاگین تا اتمام مدت زمان ذکر شده متوقف می شود. این پدیده (به اصطلاح throttling) تنها مختص به آدرس ایمیل / نام کاربری و آدرس IP کاربر می باشد:
<?php
namespace App\Http\Controllers\Auth;
use App\User;
use Validator;
use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\ThrottlesLogins;
use Illuminate\Foundation\Auth\AuthenticatesAndRegistersUsers;
class AuthController extends Controller
{
use AuthenticatesAndRegistersUsers, ThrottlesLogins;
// Rest of AuthController class...
}
احراز هویت کاربران به صورت دستی
البته لزومی ندارد حتما از کنترلرهای Authentication که با فرم ورک لاراول در اختیار برنامه نویس قرار می گیرد، استفاده نمایید. در صورت تمایل می توانید این کنترلرها را حذف کنید. اما در آن صورت بایستی سنجش هویت کاربر (user authentication) را به صورت مستقیم از طریق کلاس های احراز هویت Laravel مدیریت نمایید.
می توان از طریق Auth facade به سرویس های authentication لاراول دسترسی داشته داشت. از این رو در گام نخست بایستی facade ذکر شده را با استفاده از دستور use در بالای برنامه وارد (import) کنید. حال به کاربرد متد attempt در برنامه توجه نمایید:
<?php
namespace App\Http\Controllers;
use Auth;
class AuthController extends Controller
{
public function authenticate()
{
if (Auth::attempt(['email' => $email, 'password' => $password])) {
// Authentication passed...
return redirect()->intended('dashboard');
}
}
}
متد attempt آرایه ای از جفت های کلید و مقدار را به عنوان آرگومان اول می پذیرد. مقادیر موجود در آرایه برای جستجو و دسترسی به کاربر در جدول پایگاه داده بکار می رود. بنابراین در مثال بالا کاربر به وسیله ی مقدار ستون email بازیابی می شود. اگر کاربر مورد نظر یافت شد، گذرواژه ی رمزنگاری شده (hashed password) موجود در پایگاه داده با ورودی password (رمزنگاری) که در قالب آرایه به متد فرستاده شده، مطابقت داده می شود. اگر دو گذرواژه ی رمزنگاری شده با هم منطبق بودند، در آن صورت یک session برای کاربر راه اندازی و ایجاد می شود.
چنانچه احراز هویت با موفقیت انجام شد، متد attempt مقدار بولی true و در غیر این صورت مقدار false را برمی گرداند.
متد intended کاربر را به URL ای که قبل از فیلتر شدن توسط filter Authentication سعی بر دسترسی به آن را داشت (درخواست ورود به آن صفحه را داشت اما به دلیل عدم موفقیت احراز هویت امکان دسترسی پیدا نکرد)، بازگشت (redirect) می دهد. به منظور پیشبینی و تدارک دیدن برای حالتی که صفحه ی مورد نظر در دسترس نبود، می توان یک URI ذخیره یا جایگزین (fallback) به عنوان آرگومان به این متد ارسال کرد.
اعمال شرط ها و فیلترهای بیشتر در کوئری
در صورت تمایل می توانید شرط هایی ورای گذرواژه و ایمیل کاربر به کوئری اضافه نمایید. به عنوان مثال، می توانیم شرطی تحت عنوان اینکه آیا کاربر فعال "active" هست یا خیر تعریف نمایید:
if (Auth::attempt(['email' => $email, 'password' => $password, 'active' => 1])) {
// The user is active, not suspended, and exists.
}
گفتنی است که در این مثال ها، email یک گزینه ی الزامی نمی باشد، بلکه صرفا به عنوان یک مثال به آن اشاره شده است. شما می بایست از هر اسم ستونی که با نام کاربری "username" در پایگاه داده مطابقت دارد، استفاده نمایید.
دسترسی به نمونه های خاصی از Guard
با بکار بردن متد guard در ساختمان فاساد Auth می توانید مشخص کنید کدام نمونه از guard (guard instance) را احتیاج داشته و مایل به استفاده از آن هستید. در این روش برنامه نویس قادر خواهد بود با استفاده از مدل ها یا user table ها قابل authentication کاملا مجزا، اعتبارسنجی را برای بیشتر بخش های مستقل برنامه ی خود مدیریت کنید.
اسم guard مورد نظر که به عنوان پارامتر به متد guard پاس داده شده، می بایست با یکی از guard های تنظیم شده در فایل کانفیگ auth.phpمطابقت و همخوانی داشته باشد:
if (Auth::guard('admin')->attempt($credentials)) {
//
}
خروج کاربر از برنامه و خاتمه ی session (log out)
برای خروج کاربر از برنامه، می توان از متد logout در فاساد Auth بهره گرفت. متد مزبور تمامی اطلاعات کاربر را از user session حذف می کند:
Auth::logout();
به خاطر سپردن اطلاعات کاربر
اگر می خواهید قابلیت "remember me" را در برنامه ی خود پیاده سازی کنید، در آن صورت لازم است یک مقدار بولی به عنوان آرگومان دوم به متد attempt ارسال کنید. این امکان کاربر را تا مدت زمان نامحدود یا تا زمانی که خود کاربر به صورت دستی از برنامه خارج شود، در وضعیتauthenticated نگه می دارد. لازم به ذکر است که جداول users پایگاه داده بایستی ستون remember me را در خود داشته باشند تا بتوانند مقدار توکن "remember me" را ذخیره کنند.
if (Auth::attempt(['email' => $email, 'password' => $password], $remember)) {
// The user is being remembered...
}
اگر از قابلیت به خاطر سپاری اطلاعات کاربر در سایت استفاده می کنید، می توانید از متد viaRemember برای تشخیص اینکه آیا کاربر به وسیله ی کوکی "remember me" احراز هویت شده یا خیر استفاده نمایید (برای تشخیص اینکه کاربر از چه طریقی سنجش هویت شده مثلا لاگین کرده و یا به وسیله ی قابلیت به خاطر سپاری رمز احراز هویت شده می توان از تابع "viaRemeber" استفاده کرد):
if (Auth::viaRemember()) {
//
}
دیگر روش های اعتبار سنجی
اعتبارسنجی یک نمونه User
چنانچه لازم است به یک نمونه ی user جاری اجازه ی ورود به اپلیکیشن را بدهید، در آن صورت می توانید متد login را همراه با نمونه کاربر جاری صدا بزنید (user را به عنوان پارامتر به تابع login پاس دهید). شی مورد نظر بایستی یک پیاده سازی (implementation) از کانترکتIlluminate\Contracts\Auth\Authenticatable باشد. گفتنی است مدل App\User که همراه با لاراول عرضه می شود، خود این interfaceرا پیاده سازی می کند:
Auth::login($user);
همچنین می توانید نمونه guard مورد نظر برای استفاده را مشخص نمایید. برای این منظور نمونه گارد مورد نظر را مانند نمونه ی زیر به تابع guardپاس می دهیم:
Auth::guard('admin')->login($user);
احراز هویت بر اساس ID کاربر
برای پیاده سازی قابلیت ورود کاربر به اپلیکیشن بر اساس ID، بایستی متد logUsingId را صدا بزنید. این متد کلید اصلی (primary key) کاربری که می خواهید برای ورود به برنامه سنجش هویت شود را به عنوان آرگومان می پذیرد:
Auth::loginUsingId(1);
احراز هویت کاربر برای ورود به برنامه تنها برای یک درخواست
می توانید به وسیله ی متد once به کاربر اجازه ی ورود به اپلیکیشن برای اجرای تنها یک درخواست را بدهید. در این نوع لاگین هیچ session یاCookie ای مورد استفاده قرار نگرفته و ذخیره نمی شود. این امر در ساخت یک API ناپایدار (stateless) بسیار مفید است. گفتنی است کهsignature )تعداد پارامترهای ورودی و نوع آن ها) متد once با attempt یکسان است:
if (Auth::once($credentials)) {
//
}
HTTP Basic Authentication (احراز هویت کاربر از طریق HTTP)
HTTP Basic Authentication (سنجش هویت پایه ای HTTP) یک روش سریع و آسان برای احراز هویت کاربر آن هم بدون نیاز به ایجاد یک صفحه ی ثبت ورود (login) مجزا فراهم می آورد. برای این منظور ابتدا بایستی میدلور auth.basic را به route الحاق نمایید. middleware نام برده به صورت پیش فرض همراه با لاراول در اختیار برنامه نویس قرار گرفته و نیازی به تعریف آن وجود ندارد:
Route::get('profile', ['middleware' => 'auth.basic', function() {
// Only authenticated users may enter...
}]);
پس از اضافه کردن میدلور ذکر شده به Route، هنگامی که کاربر قصد دسترسی به آدرس (route) مورد نظر در مرورگر را دارد، برنامه به صورت خودکار از کاربر می خواهد که اطلاعات لازم برای ورود به برنامه (credentials) را ارائه کند. به صورت پیش فرض، میدلور auth.basic فیلد email(در رکورد user) را به عنوان نام کاربری ("username") در نظر می گیرد.
نکته ای در خصوص FastCGI
در صورت استفاده از PHP FastCGI، ممکن است قابلیت HTTP Basic authentication به صورت آماده و بدون نیاز به تنظیم قابل استفاده نباشد و به درستی عمل نکند. برای رفع این مشکل بایستی دستورات زیر را به فایل .htaccess اضافه کنید:
RewriteCond %{HTTP:Authorization} ^(.+)$
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
احراز هویت پایه ای HTTP ناپایدار (Stateless HTTP Basic Authentication)
این امکان برای شما وجود دارد که بدون تنظیم یک identifier cookie در session، از قابلیت احراز هویت پایه ای HTTP استفاده کنید. این کار به خصوص برای تصدیق اعتبار و سنجش هویت API ها مناسب می باشد.
برای این منظور کافی است یک Middleware تعریف کنید که متد onceBasic را صدا می زند. اگر تابع مزبور هیچ پاسخی برنگرداند، درخواست بیشتر به داخل برنامه راه می یابد:
<?php
namespace Illuminate\Auth\Middleware;
use Auth;
use Closure;
class AuthenticateOnceWithBasicAuth
{
public function handle($request, Closure $next)
{
return Auth::onceBasic() ?: $next($request);
}
}
در گام بعدی، route middleware را ثبت نموده و سپس آن را به یک route الحاق کنید:
Route::get('api/user', ['middleware' => 'auth.basic.once', function() {
// Only authenticated users may enter...
}]);
بازگردانی و تنظیم مجدد گذرواژه
ملاحظاتی در خصوص پایگاه داده
اغلب برنامه های تحت وب یک مکانیزم آسان برای بازگردانی گذرواژه های فراموش شده یا از دست رفته ارائه می کند. بجای اینکه شما را مجبور کند قابلیت بازگردانی گذرواژه را برای هر اپلیکیشن مجددا پیاده سازی کنید، لاراول متدهای کارامدی برای ارسال password reminder و اجرای فرایند بازگردانی گذرواژه فراهم می کند که در زیر به شرح آن ها می پردازیم.
برای شروع اطمینان حاصل کنید مدل App\User کانترکت Illuminate\Contracts\Auth\CanResetPassword را پیاده سازی می کند. لازم است یادآور شویم که مدل App\User (که به صورت پیش فرض با فریم ورک لاراول ارائه می شود) خود این interface را پیاده سازی می کند. این مدل از مشخصه ی (trait) Illuminate\Auth\Passwords\CanResetPassword به منظور دسترسی به متدهای لازم برای پیاده سازیinterface ذکر شده در بالا می گیرد.
ایجاد Migration برای جدول ذخیره ی reset token های گذرواژه
در ادامه باید یک جدول ایجاد شود که token های بازیابی گذرواژه (password reset tokens) را در خود ذخیره نگه دارد. Migration ویژه ی این جدول به صورت پیش فرض و آماده با فریم ورک لاراول در اختیار توسعه دهنده قرار می گیرد. این migration در پوشه یdatabase/migrations قرار دارد. کافی است دستور آرتیزان migrate را به صورت زیر اجرا نمایید:
php artisan migrate
Routing (آدرس دهی)
لاراول یک کنترلر به نام Auth\PasswordController فراهم می کند که دربردارنده ی منطق لازم بازگردانی گذرواژه ی کاربری می باشد. تمامیroute های مورد نیاز برای اجرای قابلیت بازگردانی گذرواژه را می توان با اجرای دستور make:auth ایجاد نمود:
php artisan make:auth
view ها
همان طور که قبلا نیز به آن اشاره شد لاراول تمامی view های مورد نیاز برای بازگردانی گذرواژه (password reset) را زمانی که دستورmake:auth اجرا می شود، خود ایجاد می کند. view های ذکر شده در آدرس resources/views/auth/passwords قرار داده می شوند. لازم به گفتن نیست که می توانید آن ها را در صورت تمایل مطابق نیاز خود تغییر داده و تنظیم نمایید.
کنترلر بازگردانی و تنظیم مجدد گذرواژه
پس از اینکه route ها و view های مورد نیاز برای بازگردانی گذرواژه ی کاربری را تعریف کردید، می توانید مرورگر خود را اجرا نموده و به راحتی بهroute مورد نظر به آدرس /password/reset دسترسی داشته باشید. لاراول به واسطه ی کنترلر درون ساخته ی PasswordController، منطق لازم برای ارسال لینک تنظیم مجدد گذرواژه از طریق ایمیل به کاربر و گذرواژه های بروز آوری (update password) در پایگاه داده را تدارک دیده است.
بعد از بازگردانی گذرواژه، کاربر به صورت خودکار به برنامه لاگین (وارد) شده و سپس به آدرس /home هدایت (redirect) می شود. می توانید صفحه ای (redirect location) که کاربر پس از بازگردانی گذرواژه می بایست به آن ارجاع داده شود (redirect) شود را سفارشی تنظیم نمایید. برای نیل به این هدف کافی است یک خاصیت (property) redirect به صورت زیر در کلاس PasswordController تعریف نمایید:
protected $redirectTo = '/dashboard';
به صورت پیش فرض، token های بازآوری گذرواژه پس از گذشت یک ساعت منقضی (expire) می شوند. می توانید این حالت را با مراجعه به فایل config/auth.php و تنظیم گزینه ی expire در فایل نام برده، به آسانی تغییر دهید.
سفارشی سازی (Customization)
سفارشی سازی Authentication Guard (گارد سنجش هویت)
در فایل کانفیگ auth.php ، می توانید چندین guard تنظیم کنید. این guard ها را سپس می توان برای تعریف رفتار سنجش هویت (authentication behavior) چندین user table مورد استفاده قرار داد. جهت انتخاب گارد دلخواه، بایستی خاصیت (property) $guard را به صورت زیر در کنترلر PasswordController اضافه نمایید:
protected $guard = 'admins';
سفارشی سازی password broker
>در فایل کانفیگ auth.php ، می توان چندین password broker تنظیم کرد و سپس از آن ها برای بازگردانی گذرواژه (password reset) چندین user table بهره گرفت. برای انتخاب password broker دلخواه، می بایست خاصیت $broker را به صورت زیر به کنترلرPasswordController اضافه نمایید:
protected $broker = 'admins';
اضافه کردن guard های سفارشی
می توان با بهره گیری از متد extend در فاساد Auth، گاردهای احراز هویت (authentication guard) اختصاصی خود را تعریف نمود. لازم است این فراخوانی به provider را داخل یک service provider قرار دهید:
<?php
namespace App\Providers;
use Auth;
use App\Services\Auth\JwtGuard;
use Illuminate\Support\ServiceProvider;
class AuthServiceProvider extends ServiceProvider
{
public function boot()
{
Auth::extend('jwt', function($app, $name, array $config) {
// Return an instance of Illuminate\Contracts\Auth\Guard...
return new JwtGuard(Auth::createUserProvider($config['provider']));
});
}
public function register()
{
//
}
}
همان طور که از مثال بالا مشاهده می شود، تابع callback ارسالی به متد extend باید یک پیاده سازی (implementation) ازIlluminate\Contracts\Auth\Guard را برگرداند. این interface تعداد محدودی متد دارد که بایستی برای تعریف guard سفارشی خود آن ها را پیاده سازی نمایید.
پس از تعریف گارد مورد نظر خود، می توانید آن را در فایل تنظیمات و کانفیگ guards به صورت زیر بکار ببرید:
'guards' => [
'api' => [
'driver' => 'jwt',
'provider' => 'users',
],
],
اضافه کردن User Provider های سفارشی
چنانچه برای ذخیره سازی و نگهداری اطلاعات کاربران سایت خود از پایگاه داده های رابطه ای قدیمی استفاده نمی کنید، در آن صورت می بایستauthentication user provider اختصاصی خود را به فریم ورک لاراول الحاق نمایید. به منظور تعریف یک user provider اختصاصی لازم است متد provider را در فاساد Auth فراخوانی نمایید. به یاد داشته باشید که فراخوانی تابع provider را باید در یک service provider انجام دهید:
<?php
namespace App\Providers;
use Auth;
use App\Extensions\RiakUserProvider;
use Illuminate\Support\ServiceProvider;
class AuthServiceProvider extends ServiceProvider
{
public function boot()
{
Auth::provider('riak', function($app, array $config) {
// Return an instance of Illuminate\Contracts\Auth\UserProvider...
return new RiakUserProvider($app['riak.connection']);
});
}
public function register()
{
//
}
}
پس از ثبت provider دلخواه (به وسیله ی تابع provider)، می توانید از user provider جدید مقیم در فایل تنظیمات (config)config/auth.php بجای provider قدیمی استفاده نمایید.
ابتدا بایستی یک provider ایجاد نمایید که از driver جدید شما استفاده می کند:
'providers' => [
'users' => [
'driver' => 'riak',
],
],
پس از آن می توانید provider مزبور را در فایل تنظیمات guards به صورت زیر بکار ببرید:
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
],
User Provider Contract
پیاده سازی های (implementation) Illuminate\Contracts\Auth\UserProvider تنها وظیفه ی واکشی و استخراج پیاده سازی هایIlluminate\Contracts\Auth\Authenticatable از یک سیستم ذخیره سازی ماندگار اطلاعات، همچون MySQL، Riak را بر عهده دارند. دوinterface ذکر شده در بالا این امکان را برای مکانیزم های سنجش هویت لاراول فراهم می کنند تا صرف نظر از اینکه داده های کاربری چگونه در دیتابیس ذخیره شده یا چه نوع کلاسی برای نمایش آن داده ها بکار می رود، به درستی به عملکرد خود ادامه دهند.
اکنون نگاه مختصری به کانترکت Illuminate\Contracts\Auth\UserProvider می اندازیم:
<?php
namespace Illuminate\Contracts\Auth;
interface UserProvider {
public function retrieveById($identifier);
public function retrieveByToken($identifier, $token);
public function updateRememberToken(Authenticatable $user, $token);
public function retrieveByCredentials(array $credentials);
public function validateCredentials(Authenticatable $user, array $credentials);
}
تابع retrieveById معمولا یک کلید به عنوان پارامتر دریافت می کند که بیان کننده ی کاربر مورد نظر می باشد، از جمله می توان به فیلد ID خود افزاینده(auto-incrementing) پایگاه داده ی MySQL اشاره نمود. آن پیاده سازی Authenticatable ای که با پارامتر ورودی ID منطبق باشد، بایستی توسط متد ذکر شده بازگردانی شود.
تابع retrieveByToken همان طور که از نامش پیداست یک کاربر را بر اساس$identifier منحصر بفرد آن کاربر و نیز "remember me"$token (مرابخاطر بسپار) که در فیلد remember_token ذخیره می شود، واکشی می نماید. این متد بایستی مانند متد retrieveById، پیاده سازی (implementaion) Authenticatable را به عنوان خروجی برگرداند.
متد updateRememberToken فیلد $user ستون remember_token را با استفاده از $token جدید که به عنوان پارامتر دوم به متد ارسال شده، بروز آوری می کند. این token می تواند توکن جدید باشد که با یک تلاش موفقیت آمیز "remember me" و ورود کاربر به برنامه تخصیص داده می شود و یا یک توکن null که با خروج کاربر از برنامه اختصاص می یابد.
متد retrieveByCredentials به هنگام ورود کاربر به برنامه، آرایه ای از credentials که به (به صورت آرگومان به) متد Auth::attemptارسال شده را به عنوان پارامتر ورودی می پذیرد. این متد سپس باید از سیستم ذخیره ماندگار اطلاعات (underlying storage system) برای آن کاربر که با آرگومان credentials ارسالی همخوانی دارد کوئری بگیرد (متد retrieveByCredentials معمولا با یک شرطwhere از $credentials['username'] کوئری می گیرد). متد مزبور سپس باید یک پیاده سازی از UserInterface را به عنوان خروجی بازگرداند.
دقت داشته باشید که این متد نباید تحت هیچ شرایطی عملیات اعتبارسنجی (گذرواژه) یا احراز هویت (کاربر) را انجام دهد.
متد validateCredentials برای احراز هویت کاربر می بایست $user را با $credentials تطبیق دهد. برای مثال، این متد ممکن است برای سنجش هویت کاربر، رشته ی $user->getAuthPassword() را با Hash::make of $credentials['password'] مقایسه کند. گفتنی است که متد نام برده می بایست فقط credentials (اعتبارنامه: گذرواژه، نام کاربری یا آدرس ایمیل) کاربر را مورد اعتبارسنجی قرار داده (validate) و در خروجی یک مقدار بولی را برگرداند.
Authenticatable Contract
پس از بررسی تمامی متدهای موجود در UserProvider به تشریح کانترکت Authenticatable می پردازیم. یادآور می شویم که provider بایستیimplementation های این interface را از توابع retrieveById و retrieveByCredentials بازگردانی نماید:
<?php
namespace Illuminate\Contracts\Auth;
interface Authenticatable {
public function getAuthIdentifierName();
public function getAuthIdentifier();
public function getAuthPassword();
public function getRememberToken();
public function setRememberToken($value);
public function getRememberTokenName();
}
این interface بسیار ساده می باشد. متد getAuthIdentifierName می بایست اسم فیلد کلید اصلی ("primary key") و متدgetAuthIdentifier نیز می بایست خود کلید اصلی کاربر را بازیابی نماید. در بخش سمت مدیر (back-end) پایگاه داده ی MySQL، این کلید همان primary key خود افزاینده (auto-incrementing) می باشد. متد getAuthPassword گذرواژه ی رمزنگاری شده (hashed password) کاربر را برمی گرداند. این interface به سیستم احراز هویت امکان می دهد تا صرف نظر از (نوع) ORM یا لایه ی انتزاعی ذخیره اطلاعات (storage abstraction layer) مورد استفاده، با هر کلاس User ای تعامل داشته و کار کند. به صورت پیش فرض لاراول یک کلاس به نامUser در پوشه ی app برای شما در نظر گرفته که interface مذکور را پیاده سازی می کند. برای مشاهده ی نمونه implementation می توانید به این کلاس مراجعه نمایید.
رخدادها
لاراول در طول فرایند احراز هویت چندین رخداد مختلف صدا زده و اجرا می کند. می توانید listener ها (گوش فراخوان ها) را درEventServiceProvider به event ها الحاق کنید:
protected $listen = [
'Illuminate\Auth\Events\Attempting' => [
'App\Listeners\LogAuthenticationAttempt',
],
'Illuminate\Auth\Events\Login' => [
'App\Listeners\LogSuccessfulLogin',
],
'Illuminate\Auth\Events\Logout' => [
'App\Listeners\LogSuccessfulLogout',
],
'Illuminate\Auth\Events\Lockout' => [
'App\Listeners\LogLockout',
],
];